//top.cpp
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include <verilated.h>   //访问验证程序例程的库
#include <verilated_vcd_c.h>  //向VCD文件中写入波形
#include "Vtop.h"       //包含top模型的顶层文件转化的类

#define MAX_SIM_TIME 100   //最大仿真时间
vluint64_t sim_time = 0;
/*
int top(int argc, char** argv) 
{
    //构建VerilatedContext以保留模拟时间
     VerilatedContext* contextp = new VerilatedContext;
     contextp->commandArgs(argc, argv);
     //用VerilatedContext实例化自己的顶层类
     Vtop* top = new Vtop{contextp};
     //开启波形追踪
     Verilated::traceEverOn(true);
     VerilatedVcdC *m_trace = new VerilatedVcdC;
     top->trace(m_trace, 5); //顶层类设置测试波形参数
     m_trace->open("waveform.vcd"); //设置波形写入的文件
     
     while (sim_time < MAX_SIM_TIME) {
         int a = rand() &1;
         int b = rand() &1;
         top->a = a; //实例化模型的信号赋值
         top->b = b;
         top->eval(); //评估信号    
         m_trace->dump(sim_time); //将信号写入波形
         sim_time++;        
         printf("a = %d, b = %d,f = %d\n",a,b,top->f);
         assert(top->f == (a^b));
     }
     m_trace->close();
     top->final();
     delete top;
     return 0;
}

// 这里实际上是仿真了单个时钟周期
void single_cycle(Vtop* top) {
  top->clk = 0; top->eval(); //时钟脚写0，生效硬件
  top->clk = 1; top->eval(); //时钟脚写1，生效硬件
}

//复位引脚置1，持续的时钟周期
void reset(Vtop* top, int n) {
  top->rst = 1;  //复位脚写1，生效硬件
  while (n -- > 0) single_cycle(top); //流逝一个时钟周期
  top->rst = 0;
}

int light(int argc, char** argv) 
{
    //构建VerilatedContext以保留模拟时间
     VerilatedContext* contextp = new VerilatedContext;
     contextp->commandArgs(argc, argv);
     //用VerilatedContext实例化自己的顶层类
     Vtop* top = new Vtop{contextp};
     //开启波形追踪
     Verilated::traceEverOn(true);
     VerilatedVcdC *m_trace = new VerilatedVcdC;
     top->trace(m_trace, 5); //顶层类设置测试波形参数
     m_trace->open("waveform.vcd"); //设置波形写入的文件
     
     reset(top, 10);  //复位10个时钟周期
     while (sim_time < MAX_SIM_TIME) {
        single_cycle(top); //模拟外部晶振，提供时钟信号输入，使verilog编写的逻辑电路运行
        m_trace->dump(sim_time); //将信号写入波形
        sim_time++;    //时钟周期计数    
        printf("clk = %d, rst = %d, led = %d\n",top->clk,top->rst,top->led);
        //assert(top->f == (a^b));
     }
     m_trace->close();
     top->final();
     delete top;
     return 0;
}
*/

int mux21(int argc, char** argv) 
{
    //构建VerilatedContext以保留模拟时间
     VerilatedContext* contextp = new VerilatedContext;
     contextp->commandArgs(argc, argv);
     //用VerilatedContext实例化自己的顶层类
     Vtop* top = new Vtop{contextp};
     //开启波形追踪
     Verilated::traceEverOn(true);
     VerilatedVcdC *m_trace = new VerilatedVcdC;
     top->trace(m_trace, 5); //顶层类设置测试波形参数
     m_trace->open("waveform.vcd"); //设置波形写入的文件
     
     while (sim_time < MAX_SIM_TIME) {
        unsigned char a = rand() &3;
        unsigned char b = rand() &3;
        unsigned char c = rand() &3;
        unsigned char d = rand() &3;
        unsigned char sel = rand() &3;
        top->a = a; //实例化模型的信号赋值
        top->b = b;
        top->c = c;
        top->d = c;
        top->sel = sel;

        top->eval(); //评估信号    
        m_trace->dump(sim_time); //将信号写入波形
        sim_time++;    //时钟周期计数    
        printf("a = %d, b = %d, c = %d, d = %d, sel = %d, y = %d, led = %d\n",top->a,top->b,top->c,top->d,top->sel,top->y,top->led);
        //assert(top->y == (a^b));
     }
     m_trace->close();
     top->final();
     delete top;
     return 0;
}

int main(int argc, char** argv) {
    //top(argc, argv);
    //light(argc, argv);
    mux21(argc, argv);
}